using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Komires.MataliPhysics;


namespace MySimpleScene
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        private Texture2D background;

        public PhysicsEngine Engine;
        public SimpleScene simpleScene;
        public PhysicsScene GameScene;

        public Dictionary<string, DemoMesh> Meshes;
        public Dictionary<string, Texture2D> Textures;

        public IDemoScene Scene;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            graphics.PreferredBackBufferWidth = 1920;
            graphics.PreferredBackBufferHeight = 1200;

            Meshes = new Dictionary<string, DemoMesh>();
            Textures = new Dictionary<string, Texture2D>();

            Scene = null;

            Engine = new PhysicsEngine("Engine 1");
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // Load The scene and load a background picture
            background = Content.Load<Texture2D>(@"Images\background");

            // Load meshes and textures to the game
            Meshes.Add("Box", new DemoMesh(this, Content.Load<Model>(@"Meshes\Box")));
            Meshes.Add("Sphere", new DemoMesh(this, Content.Load<Model>(@"Meshes\basketball")));
            Meshes.Add("Blabla", new DemoMesh(this, Content.Load<Model>(@"Meshes\blabla")));
            Meshes.Add("Shot", new DemoMesh(this, Content.Load<Model>(@"Meshes\n_mesh\ball")));
            Meshes.Add("BasketStruct", new DemoMesh(this, Content.Load<Model>(@"Meshes\n_mesh\complete_basket")));
            Textures.Add("Default", Content.Load<Texture2D>(@"Images\Default"));
            Textures.Add("Brass", Content.Load<Texture2D>(@"Images\Brass"));
            Textures.Add("BasketBall", Content.Load<Texture2D>(@"Images\basketball"));

            simpleScene = new SimpleScene(this, "My Map", 1, "Simple Scene");

            // Create a new scene in which everything will happen
            Scene = simpleScene;
            Scene.Create();
            Scene.Refresh(0.0);
        }

        protected override void Update(GameTime gameTime)
        {
            double time = gameTime.ElapsedGameTime.TotalSeconds;

            Scene.PhysicsScene.Simulate(time);

            base.Update(gameTime);
        }

        public static void CreateSharedShapes(Game1 demo, PhysicsScene scene)
        {
            ShapePrimitive shapePrimitive = null;
            Shape shape = null;

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Box");
            shapePrimitive.CreateBox(1.0f);
            shape = scene.Factory.ShapeManager.Create("Box");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            // Add a new sphere to the shape manager
            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Sphere");
            shapePrimitive.CreateSphere(1.0f);
            shape = scene.Factory.ShapeManager.Create("Sphere");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Shot");
            shapePrimitive.CreateBox(1.0f);
            shape = scene.Factory.ShapeManager.Create("Shot");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            /*shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("BasketStruct");
            shapePrimitive.CreateBox(1.0f);
            shape = scene.Factory.ShapeManager.Create("BasketStruct");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);*/
 
            /*shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Blabla");
            shapePrimitive.CreateSphere(1.0f);
            shape = scene.Factory.ShapeManager.Create("Blabla");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);*/

            // Declare and initialize the translation vector of geometrical center 
            // with negated value returned by GetCenterTranslation function
            // after use MoveToCenter function in TriangleMesh class for hemisphere         
        }

        // Non usefull right now - To use if you want to display easily any information on the screen
        public void DrawInfo(DrawMethodArgs args)
        {
            PhysicsScene scene = Engine.Factory.PhysicsSceneManager.Get(args.OwnerIndex);

            int physicsObjectCount = scene.TotalPhysicsObjectCount;
            int constraintCount = scene.TotalConstraintCount;
            int contactPointCount = scene.TotalContactPointCount;

            spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.Default, RasterizerState.CullNone);

            spriteBatch.End();
        }

        protected override void Draw(GameTime gameTime)
        {
            // TODO: Add your drawing code here
            double time = gameTime.ElapsedGameTime.TotalSeconds;

            // Draw without the synchronization
            GraphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);

            Scene.PhysicsScene.Draw(time);

            // Update to the vertical retrace
            base.Draw(gameTime);
        }

    }
}
